﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.Xml;
using System.IO;
using Ultima;

namespace RunUOGenerator
{
    public partial class frmMain : Form
    {
        private bool NeedToSave = false;

        private TabControl tabControl = new TabControl();

        private Module _Module = new Module();
        private UOItem CurrentUOItem = new UOItem();

        public Module Module { get { return _Module; } set { _Module = (Module)value; GenerateTabPages(); } }
 
        public frmMain()
        {
            InitializeComponent();
        }

        /// <summary>
        /// This method creates the tab pages from the XML dictated in Module.Layout.
        /// </summary>
        public void GenerateTabPages()
        {
            //try
            //{
                // Get out pages.
                foreach (XmlNode node in Module.Layout["Pages"].ChildNodes)
                {
                    // Make sure this node is a page.
                    if (node.Name.ToLower() == "page")
                    {
                        TabPage page = new TabPage();

                        // Scroll through all the attributes in page.
                        foreach (XmlAttribute attribute in node.Attributes)
                        {
                            switch (attribute.Name.ToLower())
                            {
                                case "name":
                                    page.Name = attribute.Value;
                                    break;
                                case "text":
                                    page.Text = attribute.Value;
                                    break;
                            }
                        }

                        // Add the page into the tab control after we build the page futher.
                        tabControl.TabPages.Add(BuildPage(page, node));
                        this.panelMain.Controls.Add(tabControl);
                        tabControl.Dock = DockStyle.Fill;
                    }
                }
            //}
            //catch (Exception)
            //{
            //    MessageBox.Show("Uhh no, there was an error while reading one of this modules XML files!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            //}
        }

        private TabPage BuildPage(TabPage page, XmlNode node)
        {
            // Take a look into the controls section of the Page node.
            foreach (XmlNode control in node["Controls"].ChildNodes)
            {
                // Make sure this is the control node.
                if (control.Name.ToLower() == "control")
                {
                    BuildControl(control, page);
                }
                else if (control.Name.ToLower() == "groupbox")
                {
                    BuildGroupBox(page, control);
                }
            }

            return page;
        }

        private TabPage BuildGroupBox(TabPage page, XmlNode node)
        {
            GroupBox box = new GroupBox();

            // Get the groupbox attributes
            try { box.Text = node.Attributes["Text"].Value; }
            catch (Exception) { }
            try { box.Location = new Point(int.Parse(node.Attributes["X"].Value), box.Location.Y); }
            catch (Exception) { }
            try { box.Location = new Point(box.Location.X, int.Parse(node.Attributes["Y"].Value)); }
            catch (Exception) { }
            try { box.Width = int.Parse(node.Attributes["Width"].Value); }
            catch (Exception) { }
            try { box.Height = int.Parse(node.Attributes["Height"].Value); }
            catch (Exception) { }


            // Take a look into the controls section of the Page node.
            foreach (XmlNode control in node["Controls"].ChildNodes)
            {
                // Make sure this is the control node.
                if (control.Name.ToLower() == "control")
                {
                    BuildControl(control, page, box);
                }
            }

            page.Controls.Add(box);
            return page;
        }

        private void BuildControl(XmlNode control, TabPage page)
        {
            BuildControl(control, page, null);
        }

        private void BuildControl(XmlNode control, TabPage page, Control baseControl)
        {
            // If this attribute is missing, then bad things will happen.
            if (control.Attributes["Type"] != null)
            {
                BaseTabControl btc = new BaseTabControl();
                
                //////////////////////////////////////////////////
                // THIS IS WHERE WE BUILD OUR SPECIAL CONTROLS!!!
                // NOTE: We need this because we have to set/get 
                //       variables, but most of all we need this
                //       for ATTRIBUTE!
                //////////////////////////////////////////////////
                switch (control.Attributes["Type"].Value.ToLower())
                {
                    case "label":
                        btc = new LabelControl();
                        string text = "";
                        try { text = control.Attributes["Text"].Value; }
                        catch (Exception) { }
                        btc.Text = text;
                        break;
                    case "numericupdown":
                        btc = new UpDownControl();
                        UpDownControl udc = (UpDownControl)btc;
                        try { udc.SkipValue = control.Attributes["SkipValue"].Value; }
                        catch (Exception) { }
                        break;
                    case "itemtype":
                        btc = new ItemTypeControl();
                        BuildItemType(btc, control.Attributes["Load"].Value);
                        break;
                    case "textbox":
                        btc = new TextControl();
                        break;
                    case "hue":
                        btc = new HueControl();
                        break;
                    case "checkbox":
                        btc = new CheckboxControl();
                        CheckboxControl cbc = (CheckboxControl)btc;
                        try { cbc.OverrideValue = control.Attributes["OverrideValue"].Value; }
                        catch (Exception) { }
                        break;
                    case "combobox":
                        btc = new ComboControl();
                        ComboControl cb = (ComboControl)btc;
                        try 
                        { 
                            string file = control.Attributes["Load"].Value;
                            if (file != "")
                                LoadComboBox(cb, file, "false");
                        }
                        catch (Exception) { }
                        break;
                }

                // Assign the attribute
                try { btc.Attribute = control.Attributes["Attribute"].Value; }
                catch (Exception) { }

                // Scroll through the attributes in the current control node and add them to our special control.
                foreach (XmlAttribute attribute in control.Attributes)
                {
                    switch (attribute.Name.ToLower())
                    {
                        case "text":
                            btc.Text = attribute.Value;
                            break;
                        case "width":
                            btc.Width = int.Parse(attribute.Value);
                            break;
                        case "height":
                            //btc.Height = int.Parse(attribute.Value);
                            break;
                       case "attribute":
                            btc.Attribute = attribute.Value;
                            break;
                        case "x":
                            btc.Location = new Point(int.Parse(attribute.Value), btc.Location.Y);
                            break;
                        case "y":
                            btc.Location = new Point(btc.Location.X, int.Parse(attribute.Value));
                            break;
                    }
                }

                try
                {
                    btc.ValueChanged += new EventHandler(BTC_ValueChanged);
                }
                catch (Exception ex)
                {
                    Debug.WriteLine(ex.Message);
                }

                // Should we add this to a groupbox?
                if (baseControl != null)
                {
                    baseControl.Controls.Add(btc);
                }
                else
                {
                    // Now add these controls to the page.
                    page.Controls.Add(btc);
                }
            }
        }

        /// <summary>
        /// This is an event used to capture when a BaseTabControl has been changed.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        private void BTC_ValueChanged(object sender, EventArgs args)
        {
            if(sender is BaseTabControl)
            {
                BaseTabControl btc = (BaseTabControl)sender;
                Debug.WriteLine("Object: " + btc.GetType().ToString() + " Value: " + btc.Value);
            }
        }

        private void BuildItemType(Control control, string filepath)
        {
            // Make sure this is the control we are looking for.
            if (control is ItemTypeControl)
            {
                ItemTypeControl cControl = (ItemTypeControl)control;
                cControl.DocumentPath = Program.ModuleLocation + "\\" + filepath;
                cControl.LoadDocument();
                cControl.ItemChanged += new EventHandler(ItemTypeControl_ItemChanged);
            }
        }

        private void LoadComboBox(Control combControl, string filepath, string registerSelect)
        {
            if (filepath == "" || filepath == null)
                return;

            Debug.WriteLine(Program.ExecutionLocation + "\\" + Program.ModuleLocation + "\\" + filepath);
            // Make sure this is the control we are looking for.
            if (combControl is ComboControl)
            {
                ComboControl cControl = (ComboControl)combControl;

                // Make a new XmlDoc, load it,
                XmlDocument doc = new XmlDocument();
                doc.Load(Program.ExecutionLocation + "\\"+ Program.ModuleLocation + "\\" + filepath);
                // play with it,
                foreach (XmlNode node in doc["Items"])
                {
                    string nameVal = "";
                    string baseVal = "";
                    try { nameVal = node.Attributes["Name"].Value; }
                    catch (Exception) { }
                    try { baseVal = node.Attributes["Base"].Value; }
                    catch (Exception) { }

                    // feels good man.
                    cControl.AddItem(nameVal, baseVal);
                }
            }
        }

        private int getProgressBarIncrementMax()
        {
            return toolStripProgressBar.Maximum;
        }

        private void incrementProgressBar(int value)
        {
            toolStripProgressBar.Increment(value);
        }

        private void clearProgressBar(int value)
        {
            toolStripProgressBar.Value = 0;
        }

        private void ItemTypeControl_ItemChanged(object sender, EventArgs e)
        {
            // Make sure this is the control we are looking for.
            if (sender is ItemTypeControl)
            {
                ItemTypeControl cControl = (ItemTypeControl)sender;
                CurrentUOItem = cControl.UOItem;

                // If this is null then bad stuff could happen.
                if (CurrentUOItem.GumpID != "")
                {
                    try
                    {
                        Bitmap gumpImage = Gumps.GetGump(int.Parse(CurrentUOItem.GumpID));
                        gumpPictureBox.BackgroundImage = gumpImage;
                    }
                    catch (Exception)
                    {
                        toolStripStatusLabel.Text = "An error was thrown while generating a bitmap. Is UO Installed?";
                    }
                }
                else
                {
                    gumpPictureBox.BackgroundImage = null; 
                }

                // If this is null then bad stuff could happen.
                if (CurrentUOItem.ItemID != "")
                {
                    try
                    {
                        Bitmap itemImage = new Bitmap(Art.GetStatic(int.Parse(CurrentUOItem.ItemID)));
                        itemPictureBox.BackgroundImage = itemImage;
                    }
                    catch (Exception)
                    {
                        toolStripStatusLabel.Text = "An error was thrown while generating a bitmap. Is UO Installed?";
                    }
                }
                else
                {
                    itemPictureBox.Image = null;
                }
            }
        }

        // Capture the closed event.
        private void frmMain_FormClosed(object sender, FormClosedEventArgs e)
        {
            // Makes sure the application really closes down.
            Application.Exit();
        }

        private void generateScriptToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //GenerateScript();
            CodeGenerator codeGen = new CodeGenerator(_Module, tabControl, CurrentUOItem, "Bob.cs");
            toolStripStatusLabel.Text = "Generating file...";
            if (!codeGen.GenerateScript())
            {
                toolStripStatusLabel.Text = "There was an error while creating the script file.";
            }
            else
            {
                toolStripStatusLabel.Text = "Your script was created successfully!";
            }
        }

        private void frmMain_Shown(object sender, EventArgs e)
        {
            this.Text = "RunUO " + Module.Title;
        }

        private void switchModuleToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // Check to see if we need to save this project
            frmStartup frmStartup = new frmStartup();
            this.Hide();
            frmStartup.Show();
        }

        private void saveProjectToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ProjectWriter writer = new ProjectWriter();
            SaveFileDialog sfd = new SaveFileDialog();
            sfd.Filter = "Generator Project *.uogp|*.uogp|All Files *.*|*.*";


            if (sfd.ShowDialog() == DialogResult.OK)
            {
                writer.Filename = sfd.FileName;
            }

            foreach (TabPage page in tabControl.TabPages)
            {
                Debug.WriteLine(page.Text);

                foreach (Control control in page.Controls)
                {
                    // Check to see if it is a GroupBox if it is we need to go in there
                    if (control is GroupBox)
                    {
                       // Debug.WriteLine(control.ToString());
                        GroupBox gb = (GroupBox)control;
                        foreach (Control gbControl in gb.Controls)
                        {
                            if (gbControl is BaseTabControl)
                            {
                                BaseTabControl btc = (BaseTabControl)control;
                                writer.WriteControl(btc.Attribute, btc.Value);
                                //Debug.WriteLine(control.ToString());
                            }
                        }
                    }
                    else if (control is BaseTabControl)
                    {
                        BaseTabControl btc = (BaseTabControl)control;
                        writer.WriteControl(btc.Attribute, btc.Value);
                        //Debug.WriteLine(control.ToString());
                    }
                }
            }

            writer.Flush();
            writer.Close();

            toolStripStatusLabel.Text = "Your project was successfully saved.";
            Debug.WriteLine("Project Saved.");
        }

        private void toolStripStatusLabel_TextChanged(object sender, EventArgs e)
        {
            statusBarTimer.Enabled = true;
            statusBarTimer.Start();
        }

        private void statusBarTimer_Tick(object sender, EventArgs e)
        {
            toolStripStatusLabel.Text = "Ready";

            statusBarTimer.Enabled = false;
            statusBarTimer.Stop();
        }
    }
}
